home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / Perl / form.c < prev    next >
Text File  |  1993-10-23  |  10KB  |  424 lines

  1. /* $RCSfile: form.c,v $$Revision: 4.0.1.4 $$Date: 1993/02/05 19:34:32 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log:    form.c,v $
  9.  * Revision 4.0.1.3  1992/06/08  13:21:42  lwall
  10.  * patch20: removed implicit int declarations on funcions
  11.  * patch20: form feed for formats is now specifiable via $^L
  12.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  13.  * 
  14.  * Revision 4.0.1.2  91/11/05  17:18:43  lwall
  15.  * patch11: formats didn't fill their fields as well as they could
  16.  * patch11: ^ fields chopped hyphens on line break
  17.  * patch11: # fields could write outside allocated memory
  18.  * 
  19.  * Revision 4.0.1.1  91/06/07  11:07:59  lwall
  20.  * patch4: new copyright notice
  21.  * patch4: default top-of-form format is now FILEHANDLE_TOP
  22.  * 
  23.  * Revision 4.0  91/03/20  01:19:23  lwall
  24.  * 4.0 baseline.
  25.  * 
  26.  */
  27.  
  28. #include "EXTERN.h"
  29. #include "perl.h"
  30.  
  31. /* Forms stuff */
  32.  
  33. static int countlines();
  34.  
  35. void
  36. form_parseargs(fcmd)
  37. register FCMD *fcmd;
  38. {
  39.     register int i;
  40.     register ARG *arg;
  41.     register int items;
  42.     STR *str;
  43.     ARG *parselist();
  44.     line_t oldline = curcmd->c_line;
  45.     int oldsave = savestack->ary_fill;
  46.  
  47.     str = fcmd->f_unparsed;
  48.     curcmd->c_line = fcmd->f_line;
  49.     fcmd->f_unparsed = Nullstr;
  50. #ifndef macintosh
  51.     (void)savehptr(&curstash);
  52. #else
  53.     savehptr(&curstash);
  54. #endif
  55.     curstash = str->str_u.str_hash;
  56.     arg = parselist(str);
  57.     restorelist(oldsave);
  58.  
  59.     items = arg->arg_len - 1;    /* ignore $$ on end */
  60.     for (i = 1; i <= items; i++) {
  61.     if (!fcmd || fcmd->f_type == F_NULL)
  62.         fatal("Too many field values");
  63.     dehoist(arg,i);
  64.     fcmd->f_expr = make_op(O_ITEM,1,
  65.       arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
  66.     if (fcmd->f_flags & FC_CHOP) {
  67.         if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
  68.         fcmd->f_expr[1].arg_type = A_LVAL;
  69.         else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
  70.         fcmd->f_expr[1].arg_type = A_LEXPR;
  71.         else
  72.         fatal("^ field requires scalar lvalue");
  73.     }
  74.     fcmd = fcmd->f_next;
  75.     }
  76.     if (fcmd && fcmd->f_type)
  77.     fatal("Not enough field values");
  78.     curcmd->c_line = oldline;
  79.     Safefree(arg);
  80.     str_free(str);
  81. }
  82.  
  83. int newsize;
  84.  
  85. #define CHKLEN(allow) \
  86. newsize = (d - orec->o_str) + (allow); \
  87. if (newsize >= curlen) { \
  88.     curlen = d - orec->o_str; \
  89.     GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
  90.     d = orec->o_str + curlen;    /* in case it moves */ \
  91.     curlen = orec->o_len - 2; \
  92. }
  93.  
  94. void
  95. format(orec,fcmd,sp)
  96. register struct outrec *orec;
  97. register FCMD *fcmd;
  98. int sp;
  99. {
  100.     register char *d = orec->o_str;
  101.     register char *s;
  102.     register int curlen = orec->o_len - 2;
  103.     register int size;
  104.     FCMD *nextfcmd;
  105.     FCMD *linebeg = fcmd;
  106.     char tmpchar;
  107.     char *t;
  108.     CMD mycmd;
  109.     STR *str;
  110.     char *chophere;
  111.     int blank = TRUE;
  112.  
  113.     mycmd.c_type = C_NULL;
  114.     orec->o_lines = 0;
  115.     for (; fcmd; fcmd = nextfcmd) {
  116.     nextfcmd = fcmd->f_next;
  117.     CHKLEN(fcmd->f_presize);
  118.     /*SUPPRESS 560*/
  119.     if (s = fcmd->f_pre) {
  120.         while (*s) {
  121.         if (*s == '\n') {
  122.             t = orec->o_str;
  123.             if (blank && (fcmd->f_flags & FC_REPEAT)) {
  124.             while (d > t && (d[-1] != '\n'))
  125.                 d--;
  126.             }
  127.             else {
  128.             while (d > t && (d[-1] == ' ' || d[-1] == '\t'))
  129.                 d--;
  130.             }
  131.             if (fcmd->f_flags & FC_NOBLANK) {
  132.             if (blank || d == orec->o_str || d[-1] == '\n') {
  133.                 orec->o_lines--;    /* don't print blank line */
  134.                 linebeg = fcmd->f_next;
  135.                 break;
  136.             }
  137.             else if (fcmd->f_flags & FC_REPEAT)
  138.                 nextfcmd = linebeg;
  139.             else
  140.                 linebeg = fcmd->f_next;
  141.             }
  142.             else
  143.             linebeg = fcmd->f_next;
  144.             blank = TRUE;
  145.         }
  146.         *d++ = *s++;
  147.         }
  148.     }
  149.     if (fcmd->f_unparsed)
  150.         form_parseargs(fcmd);
  151.     switch (fcmd->f_type) {
  152.     case F_NULL:
  153.         orec->o_lines++;
  154.         break;
  155.     case F_LEFT:
  156.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  157.         str = stack->ary_array[sp+1];
  158.         s = str_get(str);
  159.         size = fcmd->f_size;
  160.         CHKLEN(size);
  161.         chophere = Nullch;
  162.         while (size && *s && *s != '\n') {
  163.         if (*s == '\t')
  164.             *s = ' ';
  165.         else if (*s != ' ')
  166.             blank = FALSE;
  167.         size--;
  168.         if (*s && index(chopset,(*d++ = *s++)))
  169.             chophere = s;
  170.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  171.             *s = ' ';
  172.         }
  173.         if (size || !*s)
  174.         chophere = s;
  175.         else if (chophere && chophere < s && *s && index(chopset,*s))
  176.         chophere = s;
  177.         if (fcmd->f_flags & FC_CHOP) {
  178.         if (!chophere)
  179.             chophere = s;
  180.         size += (s - chophere);
  181.         d -= (s - chophere);
  182.         if (fcmd->f_flags & FC_MORE &&
  183.           *chophere && strNE(chophere,"\n")) {
  184.             while (size < 3) {
  185.             d--;
  186.             size++;
  187.             }
  188.             while (d[-1] == ' ' && size < fcmd->f_size) {
  189.             d--;
  190.             size++;
  191.             }
  192.             *d++ = '.';
  193.             *d++ = '.';
  194.             *d++ = '.';
  195.             size -= 3;
  196.         }
  197.         while (*chophere && index(chopset,*chophere)
  198.           && isSPACE(*chophere))
  199.             chophere++;
  200.         str_chop(str,chophere);
  201.         }
  202.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  203.         size = 0;            /* no spaces before newline */
  204.         while (size) {
  205.         size--;
  206.         *d++ = ' ';
  207.         }
  208.         break;
  209.     case F_RIGHT:
  210.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  211.         str = stack->ary_array[sp+1];
  212.         t = s = str_get(str);
  213.         size = fcmd->f_size;
  214.         CHKLEN(size);
  215.         chophere = Nullch;
  216.         while (size && *s && *s != '\n') {
  217.         if (*s == '\t')
  218.             *s = ' ';
  219.         else if (*s != ' ')
  220.             blank = FALSE;
  221.         size--;
  222.         if (*s && index(chopset,*s++))
  223.             chophere = s;
  224.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  225.             *s = ' ';
  226.         }
  227.         if (size || !*s)
  228.         chophere = s;
  229.         else if (chophere && chophere < s && *s && index(chopset,*s))
  230.         chophere = s;
  231.         if (fcmd->f_flags & FC_CHOP) {
  232.         if (!chophere)
  233.             chophere = s;
  234.         size += (s - chophere);
  235.         s = chophere;
  236.         while (*chophere && index(chopset,*chophere)
  237.           && isSPACE(*chophere))
  238.             chophere++;
  239.         }
  240.         tmpchar = *s;
  241.         *s = '\0';
  242.         while (size) {
  243.         size--;
  244.         *d++ = ' ';
  245.         }
  246.         size = s - t;
  247.         Copy(t,d,size,char);
  248.         d += size;
  249.         *s = tmpchar;
  250.         if (fcmd->f_flags & FC_CHOP)
  251.         str_chop(str,chophere);
  252.         break;
  253.     case F_CENTER: {
  254.         int halfsize;
  255.  
  256.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  257.         str = stack->ary_array[sp+1];
  258.         t = s = str_get(str);
  259.         size = fcmd->f_size;
  260.         CHKLEN(size);
  261.         chophere = Nullch;
  262.         while (size && *s && *s != '\n') {
  263.         if (*s == '\t')
  264.             *s = ' ';
  265.         else if (*s != ' ')
  266.             blank = FALSE;
  267.         size--;
  268.         if (*s && index(chopset,*s++))
  269.             chophere = s;
  270.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  271.             *s = ' ';
  272.         }
  273.         if (size || !*s)
  274.         chophere = s;
  275.         else if (chophere && chophere < s && *s && index(chopset,*s))
  276.         chophere = s;
  277.         if (fcmd->f_flags & FC_CHOP) {
  278.         if (!chophere)
  279.             chophere = s;
  280.         size += (s - chophere);
  281.         s = chophere;
  282.         while (*chophere && index(chopset,*chophere)
  283.           && isSPACE(*chophere))
  284.             chophere++;
  285.         }
  286.         tmpchar = *s;
  287.         *s = '\0';
  288.         halfsize = size / 2;
  289.         while (size > halfsize) {
  290.         size--;
  291.         *d++ = ' ';
  292.         }
  293.         size = s - t;
  294.         Copy(t,d,size,char);
  295.         d += size;
  296.         *s = tmpchar;
  297.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  298.         size = 0;            /* no spaces before newline */
  299.         else
  300.         size = halfsize;
  301.         while (size) {
  302.         size--;
  303.         *d++ = ' ';
  304.         }
  305.         if (fcmd->f_flags & FC_CHOP)
  306.         str_chop(str,chophere);
  307.         break;
  308.     }
  309.     case F_LINES:
  310.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  311.         str = stack->ary_array[sp+1];
  312.         s = str_get(str);
  313.         size = str_len(str);
  314.         CHKLEN(size+1);
  315.         orec->o_lines += countlines(s,size) - 1;
  316.         Copy(s,d,size,char);
  317.         d += size;
  318.         if (size && s[size-1] != '\n') {
  319.         *d++ = '\n';
  320.         orec->o_lines++;
  321.         }
  322.         linebeg = fcmd->f_next;
  323.         break;
  324.     case F_DECIMAL: {
  325.         double value;
  326.  
  327.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  328.         str = stack->ary_array[sp+1];
  329.         size = fcmd->f_size;
  330.         CHKLEN(size+1);
  331.         /* If the field is marked with ^ and the value is undefined,
  332.            blank it out. */
  333.         if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
  334.         while (size) {
  335.             size--;
  336.             *d++ = ' ';
  337.         }
  338.         break;
  339.         }
  340.         blank = FALSE;
  341.         value = str_gnum(str);
  342.         if (fcmd->f_flags & FC_DP) {
  343.         sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
  344.         } else {
  345.         sprintf(d, "%*.0f", size, value);
  346.         }
  347.         d += size;
  348.         break;
  349.     }
  350.     }
  351.     }
  352.     CHKLEN(1);
  353.     *d++ = '\0';
  354. }
  355.  
  356. static int
  357. countlines(s,size)
  358. register char *s;
  359. register int size;
  360. {
  361.     register int count = 0;
  362.  
  363.     while (size--) {
  364.     if (*s++ == '\n')
  365.         count++;
  366.     }
  367.     return count;
  368. }
  369.  
  370. void
  371. do_write(orec,stab,sp)
  372. struct outrec *orec;
  373. STAB *stab;
  374. int sp;
  375. {
  376.     register STIO *stio = stab_io(stab);
  377.     FILE *ofp = stio->ofp;
  378.  
  379. #ifdef DEBUGGING
  380. #ifdef macintosh
  381.     if (debug & 256)
  382.     fprintf(perldbg,"left=%ld, todo=%ld\n",
  383.       (long)stio->lines_left, (long)orec->o_lines);
  384. #else
  385.     if (debug & 256)
  386.     fprintf(stderr,"left=%ld, todo=%ld\n",
  387.       (long)stio->lines_left, (long)orec->o_lines);
  388. #endif
  389. #endif
  390.     if (stio->lines_left < orec->o_lines) {
  391.     if (!stio->top_stab) {
  392.         STAB *topstab;
  393.         char tmpbuf[256];
  394.  
  395.         if (!stio->top_name) {
  396.         if (!stio->fmt_name)
  397.             stio->fmt_name = savestr(stab_name(stab));
  398.         sprintf(tmpbuf, "%s_TOP", stio->fmt_name);
  399.         topstab = stabent(tmpbuf,FALSE);
  400.         if (topstab && stab_form(topstab))
  401.             stio->top_name = savestr(tmpbuf);
  402.         else
  403.             stio->top_name = savestr("top");
  404.         }
  405.         topstab = stabent(stio->top_name,FALSE);
  406.         if (!topstab || !stab_form(topstab)) {
  407.         stio->lines_left = 100000000;
  408.         goto forget_top;
  409.         }
  410.         stio->top_stab = topstab;
  411.     }
  412.     if (stio->lines_left >= 0 && stio->page > 0)
  413.         fwrite(formfeed->str_ptr, formfeed->str_cur, 1, ofp);
  414.     stio->lines_left = stio->page_len;
  415.     stio->page++;
  416.     format(&toprec,stab_form(stio->top_stab),sp);
  417.     fputs(toprec.o_str,ofp);
  418.     stio->lines_left -= toprec.o_lines;
  419.     }
  420.   forget_top:
  421.     fputs(orec->o_str,ofp);
  422.     stio->lines_left -= orec->o_lines;
  423. }
  424.